package org.ricks.lambda;

import java.lang.invoke.*;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.*;

public class LambdaBinder {

    private static final Map<CacheKey, CallSite> callSiteCache = new ConcurrentHashMap<>();

    public static <T> T bind(Object instance, Method method) {
        CacheKey key = new CacheKey(instance, method);
        try {
            CallSite site = callSiteCache.computeIfAbsent(key, k -> {
                try {
                    Class<?> functionalInterface = resolveFunctionalInterface(method);
                    Method interfaceMethod = functionalInterface.getDeclaredMethods()[0];

                    // 获取并绑定实例的 MethodHandle
                    MethodHandles.Lookup lookup = MethodHandles.lookup();
                    MethodHandle specificHandle = lookup.unreflect(method);
                    specificHandle = specificHandle.bindTo(instance); // 关键：提前绑定实例

                    // 关键修复点：直接使用接口方法的类型
                    MethodType samMethodType = MethodType.methodType(
                            interfaceMethod.getReturnType(),
                            interfaceMethod.getParameterTypes()
                    );

                    // 方法句柄适配到 SAM 类型
                    MethodHandle genericHandle = specificHandle.asType(samMethodType);

                    // 修复工厂方法签名（无参数）
                    MethodType factoryType = MethodType.methodType(functionalInterface);

                    return LambdaMetafactory.metafactory(
                            lookup,
                            interfaceMethod.getName(),
                            factoryType,   // (无参)
                            samMethodType, // SAM方法类型
                            genericHandle, // 目标句柄
                            samMethodType  // instantiatedMethodType应与SAM一致
                    );
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            });
            return (T) site.getTarget().invokeExact(); // 修正：无需参数
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }



//    // 根据方法签名解析函数式接口
//    private static Class<?> resolveFunctionalInterface(Method method) {
//        int paramCount = method.getParameterCount();
//        Class<?> returnType = method.getReturnType();
//
//        if (paramCount == 0) {
//            return returnType == boolean.class ? BooleanSupplier.class : Supplier.class;
//        } else if (paramCount == 1) {
//            if (returnType == boolean.class) return Predicate.class;
//            else if (returnType == void.class) return Consumer.class;
//            else return Function.class;
//        }
//        // 其他情况可扩展（如BiFunction等）
//        throw new IllegalArgumentException("Unsupported method signature");
//    }

    private static Class<?> resolveFunctionalInterface(Method method) {
        int paramCount = method.getParameterCount();
        Class<?> returnType = method.getReturnType();
        Class<?>[] paramTypes = method.getParameterTypes();

        // 无参数
        if (paramCount == 0) {
            return returnType == boolean.class ? BooleanSupplier.class : Supplier.class;
        }
        // 单参数
        else if (paramCount == 1) {
            Class<?> paramType = paramTypes[0];
            // 处理基本类型的特化接口（如IntPredicate）
            if (paramType.isPrimitive()) {
                if (returnType == boolean.class) {
                    if (paramType == int.class) return IntPredicate.class;
                    else if (paramType == long.class) return LongPredicate.class;
                    // 其他基本类型类似处理...
                }
                // 其他返回类型处理...
            }
            // 通用泛型接口
            if (returnType == boolean.class) return Predicate.class;
            else if (returnType == void.class) return Consumer.class;
            else return Function.class;
        }
        // 双参数
        else if (paramCount == 2) {
            if (returnType == void.class) return BiConsumer.class;
            else return BiFunction.class;
        }
        throw new IllegalArgumentException("Unsupported method signature");
    }

    /** 缓存键：组合实例哈希与方法唯一标识 */
    private static class CacheKey {
        private final int instanceHash;
        private final Method method;

        CacheKey(Object instance, Method method) {
            this.instanceHash = System.identityHashCode(instance);
            this.method = method;
        }

        @Override
        public boolean equals(Object o) {
            // 1. 检查是否为同一对象
            if (this == o) return true;
            // 2. 检查类型是否匹配
            if (!(o instanceof CacheKey)) return false;
            CacheKey other = (CacheKey) o;
            // 3. 精确核对哈希码和方法相等性
            return this.instanceHash == other.instanceHash &&
                    this.method.equals(other.method);
        }

        @Override
        public int hashCode() {
            // 质数散列组合公式：减少冲突概率
            final int prime = 31;
            int result = 1;
            result = prime * result + instanceHash;
            result = prime * result + method.hashCode();
            return result;
        }
    }


}
